/*
 * @Description: 资源加载管理
 * @version: 
 * @Author: 周曾辉
 * @Date: 2020-04-03 22:38:23
 * @LastEditors: CoderXZ
 * @LastEditTime: 2020-05-28 22:42:30
 */

// 如何确定资源何时释放，我们在这里采用引用计数的方式


export interface ResInfo {
    path: "",      //资源路径
    type: null,    //资源类型
    uuids: {},     //使用的资源id
    obj: null,     //资源对象
    ref: 0,        //引用计数
};


export default class ResManager {
    private static m_instance: ResManager = null;

    private resPool: any = {};
    private uuidTable:any= {};

    public static getInstance(): ResManager {

        if (!this.m_instance) {
            this.m_instance = new ResManager();

        }

        return this.m_instance;
    }

    private constructor() {
        this.resPool = {};
        this.uuidTable = {};
    }


    public loadRes(url:string,loadType:typeof cc.Asset,completeCallback:Function):void {

        if (url in this.resPool) {
            // cc.log("loadRes: " + path + " err:already exist");
            if (completeCallback) {
                completeCallback(null, this.getRes(url));
            }
            return;
        }
        
      

        var self = this;
        cc.loader.loadRes(url, loadType, function (err, resHandle) {
            if(!err){
                // completeCallback(resHandle);

                if (url in self.resPool) {
                    if (completeCallback) {
                        completeCallback(null,resHandle);
                    }
                    return;
                }
    
                self.addUUidTable(url, resHandle, loadType);
                if (completeCallback) {
                    completeCallback(err, resHandle);
                }
            }else{
                cc.log("加载失败 url:" + url);
                return;
            }
        });
    }


    private addUUidTable(path, res, type) {
        let newInfo: ResInfo = {
            path: path,
            obj: res,
            type: type,
            uuids: {},
            ref: 0,
        };
        
        //记录所有相关资源
        for (let key of cc.loader.getDependsRecursively(res)) {
            newInfo.uuids[key] = true;
            if (key in this.uuidTable) {
                this.uuidTable[key] += 1;
            }
            else {
                this.uuidTable[key] = 1;
            }
        }
        this.resPool[path] = newInfo;
    }

    //获取实例
    public getRes(path) {
        let p = this.resPool[path];
        if (p != null) {
            p.ref++;
            if (p.type == cc.Prefab) {
                return cc.instantiate(p.obj);
            }
            else {
                return p.obj;
            }
        }
        return null;
    }

    //释放实例
    public releaseRes(path, num = 1) {
        let p = this.resPool[path];
        if (p != null) {
            p.ref -= num;
            //释放资源
            if (p.ref <= 0) {
                this.deleteRes(p);
            }
        }
    }

    //释放资源
    private deleteRes(p) {
        Object.keys(p.uuids).forEach((key) => {
            this.uuidTable[key]--;
            if (this.uuidTable[key] > 0) {
                delete p.uuids[key];
            }
            else {
                delete this.uuidTable[key];
            }
        });
        cc.loader.release(Object.keys(p.uuids));
        delete this.resPool[p.path];
    }


}
